#include "clientClient.h"

Client::Client(char *ip, unsigned int puerto,  char* path): socket(ip, puerto) {
	this->log = new std::ofstream(path);
}

int Client::leer(void *buf, size_t tamanio) {
	int bytesLeidos = 0;
	unsigned int bytesAcumulados = 0;
	while (bytesAcumulados < tamanio) {
		bytesLeidos = recv(socket.getSocketFd(), buf, tamanio, 0);
		if (bytesLeidos > 0)  // No hubo error al leer.
			bytesAcumulados += bytesLeidos;
	}
	return bytesAcumulados;
}

int Client::escribir(void *buf, size_t tamanio) {
	int bytesEsritos = 0;
	unsigned int bytesAcumulados = 0;
	while (bytesAcumulados < tamanio) {
		bytesEsritos = send(socket.getSocketFd(), buf, tamanio, 0);
		if (bytesEsritos > 0)  // No hubo error al leer.
			bytesAcumulados += bytesEsritos;
	}
	return bytesAcumulados;
}

void Client::escribirLog(const char* respuesta, const Operacion& operacion) {
	std::string respuestaDatos;
	std::string tipoRespuesta;
	std::string datoAEscribir;
	std::stringstream out;

	out << operacion.getId();  // int to string.
	datoAEscribir += out.str();  // concateno id.
	datoAEscribir += CARACTER_ESPACIO;

	datoAEscribir += operacion.getCodigoOperacion();
	datoAEscribir += CARACTER_ESPACIO;

	if (respuesta) {
		if (strlen(respuesta) > 0) {
			tipoRespuesta = RESPUESTA_CON_DATOS;
			datoAEscribir += tipoRespuesta;
			datoAEscribir += respuesta;
		}
	}
	else {
		tipoRespuesta = RESPUESTA_SIN_DATOS;
		datoAEscribir += tipoRespuesta;
	}
	datoAEscribir += SALTO_DE_LINEA;

	log->write(datoAEscribir.c_str(), datoAEscribir.size());
	log->flush();
}

Client::~Client() {
	delete log;
}

ClientSocket Client::getSocket() const {
    return socket;
}

void Client::setSocket(ClientSocket socket) {
    this->socket = socket;
}

void Client::realizarPedido(Operacion& operacion) {
	std::string resultado;
	ModeloProtocolo modelo;
	char * serializacion = NULL;

	resultado = operacion.toString();
	modelo.stringToProtocolo(resultado);
	serializacion = modelo.serializar();
	escribir((void*)serializacion,
		 LONGITUD_DATOS_INICIALES + modelo.getLongitudArgumento());

	delete [] serializacion;
}

void Client::obtenerRespuesta(const Operacion& operacion) {
	char codigo;
	char *respuestaHeader = NULL;
	char *respuestaDatos = NULL;

	int tamanio = 0;

	respuestaHeader = new char[TAMANIO_HEADER_RESPUESTA];
	leer(respuestaHeader, TAMANIO_HEADER_RESPUESTA);

	codigo = respuestaHeader[UBICACION_CODIGO_RESPUESTA];
	tamanio = (int)respuestaHeader[UBICACION_TAMANIO_RESPUESTA];

	if ((codigo == CODIGO_RESPUESTA_CON_DATO) && (tamanio > 0)) {
		respuestaDatos = new char[tamanio + TAMANIO_CARACTER_FIN_STRING];
		leer(respuestaDatos, tamanio);
		respuestaDatos[tamanio] = CARACTER_FIN_STRING;
	}

	escribirLog(respuestaDatos, operacion);

	delete []respuestaHeader;
	delete []respuestaDatos;
}
